package cn.wolfcode.wolf2w.business.service.impl;

import cn.wolfcode.wolf2w.business.api.RemoteDestinationService;
import cn.wolfcode.wolf2w.business.api.RemoteNoteService;
import cn.wolfcode.wolf2w.business.api.RemoteStrategyService;
import cn.wolfcode.wolf2w.business.api.domain.*;
import cn.wolfcode.wolf2w.business.query.SearchQuery;
import cn.wolfcode.wolf2w.business.repository.DestinationEsRepository;
import cn.wolfcode.wolf2w.business.repository.NoteEsRepository;
import cn.wolfcode.wolf2w.business.repository.StrategyEsRepository;
import cn.wolfcode.wolf2w.business.repository.UserInfoEsRepository;
import cn.wolfcode.wolf2w.business.service.ISearchService;
import cn.wolfcode.wolf2w.common.core.constant.SecurityConstants;
import cn.wolfcode.wolf2w.member.api.RemoteUserInfoService;
import cn.wolfcode.wolf2w.member.api.domain.UserInfo;
import org.apache.commons.beanutils.BeanUtils;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
import org.springframework.data.elasticsearch.core.SearchHit;
import org.springframework.data.elasticsearch.core.SearchHits;
import org.springframework.data.elasticsearch.core.query.HighlightQuery;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.stereotype.Service;

import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

@Service
public class SearchServiceImpl implements ISearchService {

    @Autowired
    private StrategyEsRepository repository;
    @Autowired
    private UserInfoEsRepository  userInfoEsRepository;
    //用于复杂的高亮查询
    @Autowired
    private ElasticsearchRestTemplate template;
    @Autowired
    private RemoteStrategyService  remoteStrategyService;
    @Autowired
    private RemoteUserInfoService remoteUserInfoService;
    @Autowired
    private NoteEsRepository  noteEsRepository;
    @Autowired
    private RemoteNoteService remoteNoteService;
    @Autowired
    private DestinationEsRepository destinationEsRepository;
    @Autowired
    private RemoteDestinationService remoteDestinationService;

    @Override
    public void saveUserInfo(UserInfoEs userInfoEs) {
        userInfoEsRepository.save(userInfoEs);
    }

    @Override
    public void saveNote(NoteEs noteEs) {
        noteEsRepository.save(noteEs);
    }

    @Override
    public void saveDestination(DestinationEs destinationEs) {
       destinationEsRepository.save(destinationEs);
    }

    @Override
    public void saveStrategy(StrategyEs strategyEs) {
        repository.save(strategyEs);
    }

    @Override
    public <T> Page<T> searchWithHighlight(Class<T> clazz, Class<?> esClazz, SearchQuery qo, String... fields) throws InvocationTargetException, IllegalAccessException {
        //创建Elasiticsearch原生查询对象
        NativeSearchQueryBuilder builder = new NativeSearchQueryBuilder();
        //设置查询条件
        builder.withQuery(
                QueryBuilders.multiMatchQuery(qo.getKeyword(),fields)
        );
        //设置分页条件
        PageRequest pageable = PageRequest.of(qo.getCurrentPage()-1, qo.getPageSize());
        builder.withPageable(pageable);

        //设置高亮查询
        List<HighlightBuilder.Field> fs = new ArrayList<>();
        for (String name : fields) {
            HighlightBuilder.Field field = new HighlightBuilder.Field(name);
            field.preTags("<span style='color:blue'>").postTags("</span>");
            fs.add(field);
        }
        builder.withHighlightFields(fs);

        //执行查询
        ArrayList list = new ArrayList<>();
        //一级hits查询
        SearchHits<?> hits = template.search(builder.build(), esClazz);
        long totalCount = hits.getTotalHits();
        //二级hits查询
        for (SearchHit<?> searchHit : hits.getSearchHits()) {
            Long id = Long.valueOf(searchHit.getId());
            T t = null;
            if (clazz == Strategy.class) {
                t = (T) remoteStrategyService.getOne(id, SecurityConstants.INNER).getData();
            }
            if (clazz == UserInfo.class) {
                t = (T) remoteUserInfoService.getOne(id, SecurityConstants.INNER).getData();
            }
            if (clazz == Note.class) {
                t = (T) remoteNoteService.getOne(id, SecurityConstants.INNER).getData();
            }
            if (clazz == Destination.class) {
                t =  (T) remoteDestinationService.getOne(id, SecurityConstants.INNER).getData();
            }
            list.add(t);
            //取回所有高亮的fields
            Map<String, List<String>> highlightFields = searchHit.getHighlightFields();
            for (String key : highlightFields.keySet()) {
                List<String> keys = highlightFields.get(key);
                StringBuffer stringBuffer = new StringBuffer();
                for (String values : keys) {
                    stringBuffer.append(values).append(" ");
                }
                String value = stringBuffer.toString();
                BeanUtils.setProperty(t,key,value);
            }
        }
        return new PageImpl<T>(list, pageable, totalCount);
    }
}
